// Yang Shuai  Copyright (c) 2022 https://yangbuyi.top.
// Copyright (c) 2022. Yangbuyi, personal projects are not allowed to be commercialized without permission.
// Please keep the information of the original author of the code. Thank you

package top.yangbuyi;

import cn.hutool.core.date.DateUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;

import java.time.ZonedDateTime;
import java.util.concurrent.*;

/**
 * @program: yangbuyi-face-demo
 * @ClassName: ExecutorCompletionServiceDemo
 * @create: 2022-06-01 00:57
 * @author yangbuyi.top
 * @since： JDK1.8
 * @ExecutorCompletionServiceDemo: $
 **/

public class ExecutorCompletionServiceDemo {
    private static final int CORE_POOL_SIZE = 5;
    private static final int MAXIMUM_POOL_SIZE = 10;
    private static final int KEEP_ALIVE_TIME = 60;
    private static final int LINKED_BLOCKING_QUEUE_CAPACITY = 1000;

    public static void main (String[] args) throws InterruptedException, ExecutionException {
        Executor executor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAXIMUM_POOL_SIZE,
                KEEP_ALIVE_TIME, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(LINKED_BLOCKING_QUEUE_CAPACITY),
                new ThreadFactoryBuilder().build(),
                new ThreadPoolExecutor.CallerRunsPolicy());
        CompletionService<Result> completionService = new ExecutorCompletionService(executor);
        for (int i = 1; i <= 5; i++) {
            completionService.submit(new Task("task" + i, i));
        }

        System.out.println("print result");

        for (int i = 1; i <= 5; i++) {
            Future<Result> future = completionService.take();
            System.out.println(future.get().result);
        }


    }

    public static class Task implements Callable<Result> {

        private String taskName;
        private long sleepSeconds;

        Task (String taskName, long sleepSeconds) {
            this.taskName = taskName;
            this.sleepSeconds = sleepSeconds;
        }

        @Override
        public ExecutorCompletionServiceDemo.Result call () throws Exception {
            // System.out.println(taskName + ":" + sleepSeconds);
            Thread.sleep(sleepSeconds * 1000);
            return new Result(sleepSeconds + ":" + taskName + " run end, time = " + DateUtil.now());
        }
    }

    public static class Result {
        private String result;

        Result (String result) {
            this.result = result;
        }
    }

}
